<?php
namespace control;
// 审批流程
class examineClass extends adIndexClass
{
    private const page  = 'examine'; # 权限页面
    private const table = 'examine'; # 涉及表
    private const title = '流程引擎';    # 标题
    private const appoint = [
        '直接上级',
        '第二级上级',
        '第三级上级',
        '第四级上级',
        '第五级上级',
        '第六级上级',
        '第七级上级',
        '第八级上级',
        '第九级上级',
        '第十级上级',
    ];
    private const continuous = [
        '最高上级',
        '第二级上级',
        '第三级上级',
        '第四级上级',
        '第五级上级',
        '第六级上级',
        '第七级上级',
        '第八级上级',
        '第九级上级',
        '第十级上级',
    ];

    /**
     * 字段初始化
     */
    public function fieldInit($fun): array
    {
        switch ($fun) {
            default:
                $tr = [
                    'type'          => [
                        'name'  => L('audit.table.lcfl'),
                        'width' => 400,
                        'sort' => 1,
                    ],
                    'target'  => [
                        'name'  => L('audit.table.lcmc'),
                        'width' => 400,
                        'sort' => 1,
                    ],
                    'updateTime'         => [
                        'name'  => L('audit.table.gxsj'),
                        'width' => 400,
                        'sort' => 1,
                    ],
                    'state'          => [
                        'name'  => L('audit.table.zhuang_tai'),
                        'width' => 300,
                    ]
                ];
        }
        return $tr;
    }

    /*列表页-查询条件*/
    public function homeOptions($isAsync = true)
    {
        /*$examineData=[];
        require_once "examineData.php";
        $flowOption = [];
        foreach ($examineData as $array) {
            foreach ($array as $k => $value) {
                $flowOption[] = $k;
            }
        }*/
        $flowOption = find(['table' => 'examine', 'field' => 'type', 'where' => " 1=1 group by type "]);
        $targetOption = find(['table' => 'examine', 'field' => 'target', 'where' => " 1=1 "]);
        //生成查询表单
        $html = $this->tableShow([
            [
                [
                    '流程分类' => selectMultiple(['name' => 'type', 'option' => array_column($flowOption['array'], 'type')]),
                    L('audit.table.lcmc') => selectMultiple(['name' => 'target', 'option' => array_column($targetOption['array'], 'target')]),
                    L('audit.table.gxsj')   => text(["name" => "time", 'laydate' => ['range' => '~']]),
                ]
            ]
        ],1);
        //返回
        if (!$isAsync) {
            return $html;
        } else {
            return json_encode(['html' => $html], 320);
        }
    }

    /**
     * 列表页~查询
     *
     * @return string
     */
    public function home(): string
    {
        $html = $this->homeOptions(false);
        $button = "";
        //返回
        return $this->homeFun($this->search($html, layout: 'pop', toolButton: $button));
    }

    /**
     * 列表页~查询结果
     *
     * @return bool|string
     */
    public function homeSearch(): bool|string
    {
        $where = '';
        //like查询数组
        $like = [];
        //全等查询数组
        $equal = [
            "type"   => $this->post('type'),
            "target" => $this->post('target'),   //审批对象
        ];
        if ($this->post('time')) {
            $where .= $this->timeComparison($this->post('time'));
        }
        //排序
        $orderBy = $this->listSort(array(
            "search"  => $this->post('list_sort_key') ?: 'updateTime',
            "sort" => $this->post('list_sort') ?: "desc",
            "array"   => array(),
        ));
        //生成查询语句
        $where .= search(array("like" => $like, "=" => $equal));
        //获取查询结果
        $page = $this->page([
            "table" => self::table,
            "where" => $where,
            "order" => $orderBy['orderBy'],
        ]);
        //获取自定义字段参数
        $installSearch = $this->installSearch();
        $body          = [];
        //表格控件区
        $liButton = array(
            $this->checkAll("listForm", "listId")
        );
        //获取记录
        $url = root . "control/adIndex.html?cla=" . $this->get('cla') . "&fun=detail";
        foreach ($page['array'] as $array) {
            //列表控件
            $dominate = $this->dominate([
                "box"    => ["name" => "listId", "value" => $array['id']],
                "detail" => ["title" => L('audit.table.bian_ji'), "click" => "newIframe('" . L('audit.table.flowInfo') . "','" . $url . '&id=' . $array['id'] . "')"],
            ]);
            $liButton[] = $dominate;
            //本行初始化
            $row = [];
            foreach ($installSearch['key'] as $key) {
                switch ($key) {
                    default:
                        $row[] = isset($array[$key]) && $array[$key] ? $array[$key] : '';
                }
            }
            $body[] = $row;
        }
        //控件
        $button = "";
        //生成页面
        $li = $this->li(array(
            "body" => $body,
            "install" => $installSearch,
            "button" => array("html" => $liButton),
            "orderBySign" => $orderBy,
            "page" => $page['para'],
        ));
        //返回
        $json['html'] = $page['hint'] . $button . "<form name='listForm'>" . $li . "</form>" . $page['button'];
        return json_encode($json, 320);
    }


    public function edit(): bool|string
    {
        $examineData=[];
        require_once "examineData.php";
        $typeOption = array_keys($examineData);
        //表单
        $html = $this->layerEdit([
            "table" => [
                [
                    L('audit.table.lcbh').'：'        => self::orderNo(),
                    must . L('audit.table.lcfl')."：" => select(["name" => "type", "title" => L('audit.table.lcfl'), 'class' => 'text', "option" => $typeOption, 'change' => 'getExamineTwo']),
                ],
                [
                    must . L('audit.table.lcmc')."：" => select(["name" => "target", "id" => 'target', "title" => L('audit.table.ming_cheng'), "class" => "select", "option" => [],]),
                ],
            ],
        ]);
        $html .= <<<EOT
        <script>
        function getExamineTwo(obj){
            const val = $(obj).val()
            if (val.length > 0){
                $.post(root+'control/adIndex.html?cla=examine&fun=getExamineData', {type: val}, function(resp){
                    if(resp.warn === 2){
                        $('#target').html(resp.html)
                    }else{
                        warn(resp.warn)
                    }
                },'json')
            }
        }
        </script>
EOT;
        //返回
        return $this->layer(["title" => L('audit.table.bian_ji_jiao_se'), "height" => 220, "html" => $html]);
    }

    public function getExamineData(): bool|string
    {
        $key  = $this->post('type');
        $data = [];
        if (empty($key)) {
            $data['warn'] = L('audit.table.lcflbnwk');
        } else {
            $examineData=[];
            require_once "examineData.php";
            $option = array_keys($examineData[$key]);
            $data   = [
                'warn' => 2,
                'html' => option(['title' => L('audit.table.lcmc'), 'option' => $option]),
            ];
        }
        return json_encode($data, 320);
    }

    /**
     * 设置条件
     *
     * @return string
     */
    public function setCondition(): string
    {
        $data  = [];
        $value = $_POST['val'];
        $mid   = $this->post('mid');
        $info  = query(self::table, " id = '$mid' ");
        if ($value) {
            $data = json_decode($value, true);
        }
        $examineData=[];
        // 字段选项
        require_once "examineData.php";
        $fieldOption = $examineData[$info['type']][$info['target']];
        if (static::isNull($fieldOption) === true) {
            $fieldOption['null'] = L('audit.table.wu_xu_tiao_jian');
        }
        // 条件选项
        $conditionOption = explode('，', para('conditionOption'));
        // 员工设置
        $spanStr = isset($data['staffName']) ? self::toSpan($data['staffName']) : '<span class="placeholder">'.L('audit.table.no_setting').'</span>';
        $objId   = getVal($data, 'id') ?: suiji();
        //表单
        $html = $this->layerEdit([
            "table"  => [
                [
                    must . L('audit.table.tjmc')."：" => text(["name" => "name", "title" => L('audit.table.tjmc'), 'class' => 'text', 'value' => getVal($data, 'name')]),
                ], [
                    must . L('audit.table.you_xian_ji')."：" => select(["name" => "level", "title" => L('audit.table.you_xian_ji'), 'class' => 'text', "option" => [1, 2, 3], 'value' => getVal($data, 'level')]),
                ],
                [
                    must . L('audit.table.shen_qing_ren')."：" => '
                    <div id="staff-box" data-box="' . $objId . '">
                        <span class="spanButton staffSel" id="setApplicant">'.L('audit.table.xuan_ze').'</span>
                        <p class="js-party-select-result-list">' . $spanStr . '</p>
                        <input id="layer' . $objId . '" type="hidden" name="staff[]" value="' . getVal($data, 'staff[]') . '">
                    </div>',
                ], [
                    must . L('audit.table.condition')."：" => select(["name" => "field", "title" => L('audit.table.xuan_ze_zi_duan'), 'class' => 'text', "option" => $fieldOption, 'value' => getVal($data, 'field')]) . ' ' . select(["name" => "range", "title" => L('audit.table.xuan_ze_fan_wei'), 'class' => 'text', "option" => $conditionOption, 'value' => getVal($data, 'range')]) . ' ' . text(['name' => 'value', 'class' => 'text', L('audit.table.zhi'), 'value' => getVal($data, 'value')])."<div>".componentClass::tipComponent(L('audit.table.jyqyywdhgk').'<br/>账套需要填写账套ID（账套详情页查看）',allowHTML:true)."</div>",
                ],
            ],
        ]);
        //返回
        return $this->layer(array(
            "title" => L('audit.table.tjfzsz'),
            "height" => 300,
            "html" => $html,
            'button' => '<button class="button" id="setConditionBtn">'.L('finance.table.que_ren').'</button>'
        ));
    }


    /**
     * 转化成span 字符串
     *
     * @param string $string
     * @return string
     */
    private static function toSpan(string $string): string
    {
        $html     = '';
        $data     = explode('，', $string);
        $interval = '';
        if ($data) {
            foreach ($data as $value) {
                $html     .= $interval . '<span>' . $value . '</span>';
                $interval = '，';
            }
        }
        return $html;
    }

    /**
     * 重写radio方法
     * @param $data
     * @return string
     */
    private static function radios($data): string
    {
        $result = $change = "";
        if (isset($data['change'])) {
            $change = " onchange='" . $data['change'] . "(this)' ";
        }
        $data['value'] = $data['value'] ?? $data['option'];
        //如果用此数组中所有的值组成的数组完全等于此数组，则说明此数组为索引数组，反之为关联数组
        if (array_values($data['value']) === $data['value']) {
            foreach ($data['value'] as $index=>$key) {
                $id = '';
                if (isset($data['id']) && $data['id']['index'] == $index ){
                    $id = $data['id']['value'];
                }
                if (isset($data['checked']) && $key == $data['checked']) {
                    $checked = "checked";
                } else {
                    $checked = "";
                }
                $result .= "<label class='radioLabel'>&nbsp;<input id='{$id}'  name='" . $data['name'] . "' type='radio' value='" . $key . "' " . $checked . $change . ">&nbsp;" . $key . "</label>";
            }
        } else {
            foreach ($data['value'] as $key => $value) {
                if (isset($data['checked']) && $key == $data['checked']) {
                    $checked = "checked";
                } else {
                    $checked = "";
                }
                $result .= "<label class='radioLabel'>&nbsp;<input name='" . $data['name'] . "' type='radio' value='" . $key . "' " . $checked . $change . ">&nbsp;" . $value . "</label>";
            }
        }
        return $result;
    }

    /**
     * 设置审批人
     *
     * @return bool|string
     */
    public function setApprover(): bool|string
    {
        $id    = $this->post('id') ?: self::getId();
        $data  = [];
        $value = $_POST['val'];
        if ($value) {
            $data = json_decode($value, true);
        }
        $spanStr = getVal($data, 'staffName') ? self::toSpan($data['staffName']) : '<span class="placeholder">未设置</span>';
        $tpl = '';
        switch (getVal($data, 'type')){
            case '指定上级':
                $tpl = select(array('name'=>'value','title'=>L('audit.table.qing_xuan_ze'),'option'=>self::appoint,'value'=>getVal($data, 'value')));
                $spanStr = '';
                break;
            case '连续多级上级':
                $tpl = select(array('name'=>'value','title'=>L('audit.table.qing_xuan_ze'),'option'=>self::continuous,'value'=>getVal($data, 'value')));
                $spanStr = '';
                break;
            case '指定职位':
                $tpl = "<span class='spanButton' id='setPosition'>".L('audit.table.xuan_ze')."</span>";
                break;
            case '审批人自选':
                $tpl = self::radios(array('name'=>'value','id'=>['index'=>2,'value'=>'staffSel'],'value'=>['不限范围','指定范围'],'checked'=>getVal($data, 'value')));
                $spanStr = getVal($data, 'value')=='不限范围'?'':$spanStr;
                break;
            case '部门负责人':
                $tpl = radio(array('name'=>'value','value'=>['发起人部门负责人','成员部门负责人'],'checked'=>getVal($data, 'value'))).componentClass::tipComponent('发起人部门负责人：将由提交人所在部门的负责人审批；成员部门负责人：将由被代提交人员的部门负责人审批');
                $spanStr = '';
                break;
            default: //指定成员
                $tpl = "<span class='spanButton' id='staffSel'>".L('audit.table.xuan_ze')."</span>";
                break;
        }
        //表单
        $html = $this->layerEdit([
            "table"  => [
                [
                    must . L('audit.table.lei_xing')."：" => radio(['name' => 'type', 'value' => ['指定成员', '指定上级', '连续多级上级', '指定职位', '审批人自选', '部门负责人'], 'checked' => getVal($data, 'type')?:'指定成员', 'change' => 'setApproverType']),
                ], [
                    must . L('audit.table.duo_ren_shen_pi')."：" => radio(['name' => 'multiType', 'value' => ['或签', '会签', '依次审批'], 'checked' => getVal($data, 'multiType')?:'或签']),
                ],
                [   must.L('audit.table.zi_dong_shen_pi')."："=>radio(array('name'=>'isAuto','value'=>['否','是'],'checked'=>getVal($data, 'isAuto')?:'否'))],
                [
                    must.'<span id="approver-category">'.L('audit.table.pChoose').'</span>' => '
                    <div id="staff-box" data-box="' . $id . '">
                        <p id="approver-append">'.$tpl.'</p>
                        <input id="layer' . $id . '" type="hidden" name="staff[]" value="' . getVal($data, 'staff[]') . '">
                        <div class="js-party-select-result-list" id="name' . $id . '">' . $spanStr . '</div>
                    </div>',
                ],
            ],
        ]);
        //返回
        return $this->layer(array(
            "title" => L('audit.table.sprsz'),
            "height" => 350,
            "html" => $html,
            'button' => '<button class="button" id="setApproverBtn">'.L('audit.table.commit').'</button>'
        ));
    }

    /**
     * 设置抄送人
     *
     * @return bool|string
     */
    public function setNotifier(): bool|string
    {
        $id    = $this->post('id') ?: self::getId();
        $data  = [];
        $value = $_POST['val'];
        if ($value) {
            $data = json_decode($value, true);
        }
        $spanStr = getVal($data, 'staffName') ? self::toSpan($data['staffName']) : '<span class="placeholder">未设置</span>';
        $tpl = '';
        switch (getVal($data, 'type')){
            case '指定成员':
                $tpl = "<span class='spanButton' id='staffSel'>".L('audit.table.pChoose')."</span>";
                break;
            case '指定上级':
                $tpl = select(array('name'=>'value','title'=>L('audit.table.qing_xuan_ze'),'option'=>self::appoint,'value'=>getVal($data, 'value')));
                $spanStr = '';
                break;
            case '指定职位':
                $tpl = "<span class='spanButton' id='setPosition'>".L('audit.table.pChoose')."</span>";
                break;

        }
        //表单
        $html = $this->layerEdit([
            "table"  => [
                [
                    must . L('audit.table.lei_xing')."：" => radio([
                        'name'                              => 'type', 'value' => ['指定成员', '指定上级', '指定职位'], 'checked' =>
                            getVal($data, 'type'), 'change' => 'setApproverType',
                    ]),
                ], [
                    must . '<span id="approver-category">'.L('audit.table.pChoose').'</span>' => '
                    <div id="staff-box" data-box="' . $id . '">
                        <p id="approver-append">'.$tpl.'</p>
                        <input id="layer' . $id . '" type="hidden" name="staff[]" value="' . getVal($data, 'staff[]') . '">
                        <div class="js-party-select-result-list" id="name' . $id . '">' . $spanStr . '</div>
                    </div>',
                ],
            ],
        ]);
        //返回
        return $this->layer(array(
            "title" => L('audit.table.csrsz'),
            "height" => 280,
            "html" => $html,
            'button' => '<button class="button" id="setNotifierBtn">'.L('audit.table.commit').'</button>'
        ));
    }

    /**
     * 查询
     */
    public static function recursive($table, $field, $where = ""): array
    {
        $data = [];
        $job  = find(['table' => $table, 'field' => $field, 'where' => $where]);
        foreach ($job['array'] as $value) {
            $value['type']     = $table;
            $value['icon']     = root . 'img/control/' . $table . '.svg';
            $value['children'] = self::recursive('staff', ' stid as id, name as deptname', " jobId = '{$value['id']}' and state !='离职' and workFlow = '已复核'");
            $data[]            = $value;
        }
        return $data;
    }

    public function getStaffInfo(): bool|string
    {
        $res['data'] = self::getStaffArray();
        return json_encode($res, 320);
    }


    /**
     * 获取员工数据
     *
     * @param string $where
     * @return array
     */
    public static function getStaffArray($where = ''): array
    {
        $where      = $where ?: "pid = '0'";
        $where      .= ' ORDER BY list ASC';
        $data       = [];
        $department = find(['table' => 'department', 'field' => 'id, name as deptname', 'where' => $where]);
        foreach ($department['array'] as $value) {
            $value['type'] = 'department';
            $value['icon'] = root . 'img/control/department.svg';
            // 获取当前部门的职位
            $value['children'] = self::recursive('job', 'DISTINCT id,name as deptname', " departmentId = '{$value['id']}' ");
            // 判断是否有子部门
            $where = " pid = '{$value['id']}' ";
            if (sqlNum('department', $where) > 0) {
                $value['children'] = array_merge($value['children'], self::getStaffArray($where));
            }
            $data[] = $value;
        }
        return $data;
    }

    /**
     * 员工选择器
     *
     * @return bool|string
     */
    public function orgTree(): bool|string
    {
        // 赋值的ID
        $id    = $this->post('id') ?? 'field-dept';
        $range = $this->post('range') ?? '';
        $other = $this->post('other') ?? '';
        // 会写的box id
        $boxId = str_replace('layer', '', $id);
        $searching = L('audit.table.searching');
        $choosedDept = L('audit.table.choosedDept');
        $noChooseDept = L('audit.table.noChooseDept');
        $confirmChoose = L('audit.table.confirmChoose');
        $html  = <<<EOT
        <div class="multi-staff clearfix">
            <div class="multi-staff-left">
                <div class="multi-staff-left-cnt">
                    <!--loading-->
                    <div class="search-loading loading-left-wrap js-search-loading"><span
                            class="search-loadingIconSmall"></span><span
                            class="search-loading-text">$searching</span>
                    </div>
                    <!--jstree-->
                    <div id="partyTree" class="multi-staff-left-cnt-list">
                        <div class="search-loading js-search-loading"><span
                                class="search-loadingIconSmall"></span><span
                                class="search-loading-text">$searching</span></div>
                        <div class="ztree-wrapper">
                            <ul id="ztreeArea" class="ztree"></ul>
                        </div>
                    </div>
                    <div class="multi-staff-left-mask js-left-mask"></div>
                </div>
            </div>
            <div class="multi-staff-right">
                <div class="multi-staff-right-title">$choosedDept</div>
                <div class="multi-staff-right-cnt">
                    <div class="js-right-col">
                        <ul id="saveNode"></ul>
                    </div>
                    <div class="multi-staff-right-no-result">$noChooseDept</div>
                </div>
            </div>
        </div>
EOT;
        $button = "<button type='button' class='button' id='confirm-staff' data-boxId='$boxId'>$confirmChoose</button>";
        $html  .= <<<EOT
        <script src="{$this->root}static/javascript/ztree.ext.js"></script>
        <script>
        $(function () {
            // 调用
            $('.winAuto').orgTree({
                all: true, //人物组织都开启
                text: '$id', // 赋值的文本框ID
                search: true, //开启搜索
                range: '$range', //范围
                other: '$other', //其他参数
                boxId: '$boxId'
            });
        });
        </script>
EOT;

        //返回
        return $this->layer(array("title" => '部门/职位/员工选择器', "height" => 550, 'width' => 650, "html" => $html, 'zindex' => 4, 'button' => $button ));
    }

    // 创建编号
    private static function orderNo(): string
    {
        return codeTemplateClass::generateCode(self::page,[
            'prefix' => 'PN',
            'table'  => self::table,
        ],[]);
    }

    public function editEdit(): bool|string
    {
        $id         = $this->post('id');
        $field      = [
            'type'   => $this->post('type'),
            'target' => $this->post('target'),
            'state'  => '启用',
        ];
        $annotation = [
            'type'   => L('audit.table.lcfl'),
            'target' => L('audit.table.lcmc'),
        ];
        $rules      = [
            'type'   => 'required',
            'target' => 'required',
        ];
        // 校验是否符合规则
        $vt     = new \verify();
        $result = $vt->setAliases($annotation)->validate($field, $rules)->isOk();
        if (!$this->power(self::page, "edit")) {
            $json['warn'] = L('audit.table.examine_edit_permission');
        } elseif ($result === false) {
            $json['warn'] = $vt->getErrs()[0]; // 多个规则提示最前面一条
        } else {
            // 去重查询
            $where = generateWhere($field);
            $info  = query(self::table, $where);
            if ($info['id']) {
                $json['warn'] =  L('audit.table.examine_repeat');
            } else {
                $field        = array_merge($field, [
                    'id'      => $id,
                    'orderNo' => self::orderNo(),
                    'stid'    => $this->control['stid'],
                    'time'    => $this->time,
                ]);
                $json['warn'] = insert(["table" => self::table, "field" => $field]);
            }
            if (in_array($json['warn'], ["新增成功", "更新成功"])) {
                //添加日志
                $text =str_replace(['{{staffName}}','{{name}}','{{id}}'],[$this->control['name'],$field['target'],$id],L('audit.table.examine_edit_text'));
                $this->logText(["type" => self::page, "text" => $text]);
                //返回
                $_SESSION['warn'] = $json['warn'];
                $json['warn']     = 2;
                $json['href']     = root . "control/adIndex.html?cla=" . $this->get('cla') . "&fun=detail&id=" . $id;
            }
        }
        return json_encode($json, 320);
    }

    /**
     * 详情
     *
     * @return string
     */
    public function detail(): string
    {
        $info = query(self::table, " id = '" . $this->get('id') . "' ");
        if (!$this->power(self::page, "see")) {
            $html =L('audit.table.examine_see_permission');
        } elseif (empty($this->get('id'))) {
            $html =L('audit.table.emptyId');
        } elseif (empty($info['id'])) {
            $html =L('audit.table.no_flow_data');
        } else {
            $data = [
                "id" => $info['id'],
            ];
            //按钮
            $button = [];
            if ($this->power(self::page, "edit")) {
                $button[] = [
                    "name"  => L('audit.table.bao_cun'),
                    "type"  => "点击事件",
                    "fun"   => "subForm('conditionForm', root + 'control/adIndex.html?cla=examine&fun=detailEdit')",
                    'style' => 'li-btn-blue-bg',
                ];
            }
            //生成表单
            $data['button'] = $this->tableShowButton($button);
            $data['html'] = $this->tableShow([
                L('audit.table.jiao_se_dang_an')   => [
                    [
                        L('audit.table.lcbh') => $info['orderNo'],
                        L('audit.table.lcfl') => $info['type'],
                        L('audit.table.lcmc') => $info['target'],
                    ],
                    [
                        L('audit.table.chuang_jian_ren')  => self::findStaff($info['stid']),
                        L('audit.table.gxsj') => $info['updateTime'],
                        L('audit.table.cjsj') => $info['time'],
                    ],
                ],
            ]);
            // 申请人
            (array)$staffData = json_decode($info['staff'], true);
            $boxId = self::getId();
            if ($staffData) {
                $spanStr       = '';
                $staffNameData = explode(';', $staffData['name']);
                foreach ($staffNameData as $name) {
                    if ($name) {
                        $spanStr .= '<span>' . $name . '</span>，';
                    }
                }
                $spanStr     = rtrim($spanStr, '，');
                $staffString = '<p class="js-party-select-result-list">' . $spanStr . '</p>';
            } else {
                $staffString = '<p class="js-party-select-result-list"></p><span class="placeholder">'.L('audit.table.chooseApply').'</span>';
            }
            $staffString .= hidden(['name' => 'staff[]', 'value' => $staffData['id'] ?? '', 'id' => $boxId]) . hidden(['name' => 'staffName[]', 'value' => $staffData['name'] ?? '',]);

            // 条件节点
            $conditionNode = '';
            // 解析条件
            (array)$conditions = json_decode($info['conditions'], true);
            // 只有一个时
            $oneStyle = '<style>.branch-box{border-bottom:none;border-top:none;min-height:255px}</style>';
            $settingCondition = L('audit.table.settingCondition');
            if (empty($conditions)) {
                $tempId           = self::getId();
                $conditionContent = '
                <div id="div' . $tempId . '">
                    <p class="placeholder">'.$settingCondition.'</p>
                    <p class="placeholder">'.$settingCondition.'</p>
                </div>'
                    . hidden(['name' => 'condition[]', 'value' => '{}', 'id' => $tempId])
                    . hidden(['name' => 'cid', 'value' => $tempId]);
                $defaultCondition = L('audit.table.defaultCondition');
                $level1 = L('audit.table.level1');
                $conditionNode = <<<EOT
                <!-- 条件分支 -->
                    $oneStyle
                    <div class="col-box">
                        <div class="condition-node">
                            <div class="condition-node-box">
                                <div class="auto-judge">
                                    <div class="title-wrapper">
                                        <span class="editable-title">$defaultCondition</span>
                                        <span class="priority-title">$level1</span>
                                        <i class="anticon anticon-close close"
                                            data-click="condition-close"></i>
                                    </div>
                                    <div class="sort-right">&gt;</div>
                                    <div class="content" data-click="condition-setting">
                                        $conditionContent
                                    </div>
                                </div>
                                <!-- 添加节点 开始-->
                                <div class="add-node-btn-box">
                                    <div class="add-node-btn">
                                        <!-- 添加节点符号 start-->
                                        <button type="button" data-click="staff-add" class="btn">
                                            <span class="iconfont"></span>
                                        </button>
                                        <!-- 添加节点符号 end-->
                                    </div>
                                </div>
                            </div>
                        </div>
                        <!-- 边界线 start-->
                </div>
EOT;
            } else {
                // 判断条件个数
                foreach ($conditions as $key => $array) {
                    $conditionLine = '';
                    if (count($conditions) === 1) {
                        $conditionNode .= $oneStyle . PHP_EOL;
                    }
                    // 第一个
                    if ($key == 0 && count($conditions) > 1) {
                        $conditionLine = <<<EOT
                    <!-- 左边界线 start-->
                        <div class="condition-cover-line">
                            <div class="top-left-cover-line"></div>
                            <div class="bottom-left-cover-line"></div>
                        </div>
EOT;
                    } // 最后一个
                    elseif (($key == count($conditions) - 1) && count($conditions) > 1) {
                        $conditionLine = <<<EOT
                    <!-- 右边界线 start-->
                        <div class="condition-cover-line">
                            <div class="top-right-cover-line"></div>
                            <div class="bottom-right-cover-line"></div>
                        </div>
EOT;
                    }
                    // 条件内容
                    $tempId           = $array['id'] ?: self::getId();
                    $you_xian_ji = L('audit.table.you_xian_ji');
                    $conditionContent = '
                        <div id="div' . $tempId . '">
                            <p>'.$you_xian_ji.'：' . $array['level'] . '</p>
                            <p class="staff-text">'.L('audit.table.shen_qing_ren').'：' . $array['staffName'] . '</p>
                            <p>' . ($array['field'] == 'null' ? L('audit.table.wu_xu_tiao_jian') : $array['field'] . '：' . $array['range'] . $array['value']) . ' </p>
                        </div>'
                        . hidden(['name' => 'condition[]', 'value' => json_encode($array, 320), 'id' => $tempId])
                        . hidden(['name' => 'cid', 'value' => $tempId]);
                    // 节点审核/抄送人
                    $conditionUser = self::parseNode($tempId, $info['node']);
                    $conditionNode .= <<<EOT
                <!-- 条件分支 -->
                    <div class="col-box">
                        <div class="condition-node">
                            <div class="condition-node-box">
                                <div class="auto-judge">
                                    <div class="title-wrapper">
                                        <span class="editable-title">{$array['name']}</span>
                                        <span class="priority-title">$you_xian_ji{$array['level']}</span>
                                        <i class="anticon anticon-close close"
                                            data-click="condition-close"></i>
                                    </div>
                                    <div class="sort-right">&gt;</div>
                                    <div class="content" data-click="condition-setting">
                                        $conditionContent
                                    </div>
                                </div>
                                <!-- 添加节点 开始-->
                                <div class="add-node-btn-box">
                                    <div class="add-node-btn">
                                        <!-- 添加节点符号 start-->
                                        <button type="button" data-click="staff-add" class="btn">
                                            <span class="iconfont"></span>
                                        </button>
                                        <!-- 添加节点符号 end-->
                                    </div>
                                </div>
                            </div>
                        </div>
                        $conditionUser
                        <!-- 边界线 start-->
                        $conditionLine
                    </div>
EOT;
                }
            }
            $shen_qing_ren = L('audit.table.shen_qing_ren');
            $addCondition = L('audit.table.addCondition');
            $flowEnding = L('audit.table.flowEnding');
            $idHtml       = hidden(['name' => 'id', 'value' => $info['id']]);
            $data['html'] .= <<<EOT
        <form name="conditionForm" onsubmit="return false">
        $idHtml
        <section class="dingflow-design">
            <div id="box-scale" class="box-scale">
                <div id="main-node">
                    <!-- 标题框 start-->
                    <div class="node-wrap">
                        <div class="node-wrap-box start-node ">
                            <div class="title"><span>$shen_qing_ren</span></div>
                            <div class="content" data-click="staff-select">
                                <div class="text" data-box="$boxId">
                                    $staffString
                                </div>
                                <i class="anticon anticon-right arrow"></i>
                            </div>
                        </div>
                        <!-- 标题框 end-->
                    </div>
                    <div class="node-body">
                        <div class="node-wrap">
                            <div class="add-node-btn-box">
                                <!-- 竖线作用 -->
                                <div class="add-node-btn"></div>
                            </div>
                        </div>
                        <div class="branch-wrap">
                            <div class="branch-box-wrap">
                                <div class="branch-box">
                                    <button class="add-branch">$addCondition</button>
                                    <!-- 条件分支 -->
                                    $conditionNode
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <!-- 竖线作用 开始-->
                <div class="node-wrap">
                    <div class="add-node-btn-box">
                        <div class="add-node-btn"></div>
                    </div>
                </div>
                <!-- 竖线作用 结尾-->
                <!-- 流程结束 开始 -->
                <div class="end-node">
                    <div class="end-node-circle"></div>
                    <div class="end-node-text">$flowEnding</div>
                </div>
                <!-- 流程结束 结尾 -->
            </div>
        </section>
EOT;
            //生成页面
            $html = $this->tab($data);
        }
        //返回
        return $html;
    }

    /**
     * 解析指定key 的节点
     *
     * @param string $key
     * @param string $body
     * @return string
     */
    public static function parseNode(string $key, string $node): string
    {
        $nodeArray     = json_decode($node, true);
        $conditionNode = '';
        // 审批人
        $rules = [
            'type'      => L('audit.table.lei_xing'),
            'value'     => L('audit.table.shu_xing'),
            'multiType' => L('audit.table.duo_ren_shen_pi'),
            'isAuto' => L('audit.table.zi_dong_shen_pi'),
            'staff[]'   => L('audit.table.shen_he_ren'),
        ];

        if ($nodeArray) {
            $data = (array)$nodeArray[$key];
            foreach ($data as $array) {
                $array['isAuto'] = $array['isAuto']??'';
                $type      = ($array['form'] == 'approver') ? '审批人' : '抄送人';
                $html      = hidden(['name' => 'node[]', 'id' => $array['id'], 'value' => json_encode($array, 320)]);
                $staffName = in_array($array['type'], ['指定上级', '连续多级上级','部门负责人']) ? $array['value'] : $array['staffName'];
                $textBody  = <<<EOT
                <p>{$rules['type']}：{$array['type']}</p>
                
EOT;
                if ($type == '审批人' and isset($array['multiType'])) {
                    $textBody .= "<p>{$rules['multiType']}：{$array['multiType']}</p><p>{$rules['isAuto']}：{$array['isAuto']}</p>";
                }
                $textBody.=<<<eof
<p class="staff-text">{$rules['staff[]']}：$staffName</p>
eof;

                $conditionNode .= <<<EOT
                <div class="condition-node">
                    <div class="node-wrap">
                        <div class="node-wrap-box">
                            <div class="title {$array['form']}">
                                <span class="iconfont editable-icon"></span>
                                <span class="editable-title">$type</span>
                                <i class="anticon anticon-close close" data-click="staff-close"></i>
                            </div>
                            <div class="content" data-click="{$array['form']}-setting">
                                <div class="text">
                                    $html
                                    <div id="div{$array['id']}">$textBody</div>
                                </div>
                                <i class="anticon anticon-right arrow"></i>
                            </div>
                        </div>
                        <div class="add-node-btn-box">
                            <div class="add-node-btn">
                                <button type="button" data-click="staff-add" class="btn"><span class="iconfont"></span></button>
                            </div>
                        </div>
                    </div>
                </div>
EOT;
            }
        }
        return $conditionNode;
    }

    /**
     * 保存审批流程
     *
     * @return bool|string
     */
    public function detailEdit(): bool|string
    {
        $id         = $this->post('id');
        $field      = [
            'staff'     => $this->post('staff'),
            'condition' => $this->post('condition'),
            'node'      => $this->post('node'),
        ];
        $annotation = [
            'staff'     => L('audit.table.shen_qing_ren'),
            'condition' => L('audit.table.tiao_jian'),
            'node'      => L('audit.table.liu_cheng'),
        ];
        $rules      = [
            'staff'     => 'required',
            'condition' => 'required',
            'node'      => 'required',
        ];
        // 校验是否符合规则
        $vt     = new \verify();
        $result = $vt->setAliases($annotation)->validate($field, $rules)->isOk();
        if (!$this->power(self::page, "edit")) {
            $json['warn'] = L('audit.table.examine_edit_permission');
        } elseif ($result === false) {
            $json['warn'] = $vt->getErrs()[0]; // 多个规则提示最前面一条
        } else {
            foreach ($field['condition'] as $value) {
                if (in_array($value, ['{}', '[]', ''])) {
                    $json['warn'] = L('audit.table.tjbnwk');
                    goto resp;
                }
            }
            // 判断条件节点是否完整
            $conditionCidArr = array_column(self::transformation($field['condition']), 'id');
            $nodeCidArr      = array_column(self::transformation($field['node']), 'cid');
            if (count($conditionCidArr) > count($nodeCidArr)) {
                $json['warn'] = L('audit.table.tjbwzqqr');
                goto resp;
            }
            $where = " id = '$id' ";
            $info  = query(self::table, $where);
            if (!$info['id']) {
                $json['warn'] =L('audit.table.not_exist_flow');
            } else {
                $field        = [
                    'staff'      => json_encode([
                        'id'   => $this->post('staff')[0],
                        'name' => $this->post('staffName')[0],
                    ], 320),
                    'conditions' => self::transformation($this->post('condition'), true),
                    'node'       => self::transformationNode(self::transformation($this->post('condition')), self::transformation($this->post('node')), true),
                ];
                $json['warn'] = static::update(["table" => self::table, "field" => $field, 'where' => $where]);
            }
            if (in_array($json['warn'], ["新增成功", "更新成功"])) {
                //添加日志
                $text =str_replace(['{{staffName}}','{{name}}','{{id}}'],[$this->control['name'],$info['target'],$id],L('audit.table.examine_edit_text'));
                $this->logText(["type" => self::page, "text" => $text]);
                //返回
                $_SESSION['warn'] = $json['warn'];
                $json['warn']     = 2;
                $json['href']     = root . "control/adIndex.html?cla=" . $this->get('cla') . "&fun=detail&id=" . $id;
            }
        }

        resp:
        return json_encode($json, 320);
    }

    /**
     * 条件转换
     *
     * @param array $arr
     * @param bool  $toJson
     * @return array|string
     */
    public static function transformation(array $arr, bool $toJson = false): array|string
    {
        $temp = [];
        foreach ($arr as $value) {
            $array = (array)json_decode(self::htmlDecode($value), true);
            if (isset($array['form']) && $array['form'] == 'approver' && in_array($array['type'], ['指定上级', '连续多级上级'])) {
                $array['staff[]'] = '';
            }
            $temp[] = $array;
        }
        if ($toJson === true) {
            $temp = json_encode($temp, 320);
        }
        return $temp;
    }


    /**
     * 节点转换
     *
     * @param array $conditions
     * @param array $nodes
     * @param bool  $toJson
     * @return array|bool|string
     */
    public static function transformationNode(array $conditions, array $nodes, bool $toJson = false): bool|array|string
    {
        $node = [];
        foreach ($conditions as $value) {
            $key = $value['id'];
            foreach ($nodes as $val) {
                if ($val['cid'] == $key) {
                    $node[$key][] = $val;
                }
            }
        }
        if ($toJson === true) {
            $node = json_encode($node, 320);
        }
        return $node;
    }


    /**
     * 员工选择器
     *
     * @return bool|string
     */
    public function materialTree(): bool|string
    {
        // 赋值的ID
        $id    = $this->post('id') ?? 'field-dept';
        $range = $this->post('range') ?? '';
        $other = $this->post('other') ?? '';
        // 会写的box id
        $boxId = str_replace('layer', '', $id);
        $html  = <<<EOT
        <div class="multi-staff clearfix">
            <div class="multi-staff-left">
                <div class="multi-staff-left-cnt">
                    <!--loading-->
                    <div class="search-loading loading-left-wrap js-search-loading"><span
                            class="search-loadingIconSmall"></span><span
                            class="search-loading-text">正在搜索，请稍候…</span>
                    </div>
                    <!--jstree-->
                    <div id="partyTree" class="multi-staff-left-cnt-list">
                        <div class="search-loading js-search-loading"><span
                                class="search-loadingIconSmall"></span><span
                                class="search-loading-text">正在搜索，请稍候…</span></div>
                        <div class="ztree-wrapper">
                            <ul id="ztreeArea" class="ztree"></ul>
                        </div>
                    </div>
                    <div class="multi-staff-left-mask js-left-mask"></div>
                </div>
            </div>
            <div class="multi-staff-right">
                <div class="multi-staff-right-title">已选择的物料</div>
                <div class="multi-staff-right-cnt">
                    <div class="js-right-col">
                        <ul id="saveNode"></ul>
                    </div>
                    <div class="multi-staff-right-no-result">未选择物料</div>
                </div>
            </div>
        </div>
        <div class="button-box">
            <button type="button" class="button" id='confirm-material' data-boxId="$boxId">确认选择</button>
        </div>
EOT;
        $html  .= <<<EOT
        <script src="{$this->root}static/javascript/ztree.ext.js"></script>
        <script>
        $(function () {
            // 调用
            $('.winAuto').orgTree({
                all: true, //人物组织都开启
                text: '$id', // 赋值的文本框ID
                search: true, //开启搜索
                range: '$range', //范围
                other: '$other', //其他参数
                boxId: '$boxId',
                type:'material',
            });
        });
        </script>
EOT;

        //返回
        return $this->layer(array("title" => L('audit.table.xuan_ze_wu_liao'), "height" => 550, 'width' => 650, "html" => $html, 'zindex' => 4));
    }


    /***********************物料分类选择***************************/
    /**
     * 查询
     */
    public static function recursiveType($table, $field, $where = ""): array
    {
        $data = [];
        $job  = find(['table' => $table, 'field' => $field, 'where' => $where]);
        foreach ($job['array'] as $value) {
            $value['deptname'] = html_entity_decode($value['deptname']);
            $value['type']     = 'department';
            $value['icon']     = root . 'img/control/department.svg';
            $value['children'] = self::recursiveType('material_type', ' DISTINCT id,name as deptname,list,time ', $where = " coid = '".self::$coid."' and pid = '{$value['id']}' order by list asc,time asc  ");
            $data[]            = $value;
        }
        return $data;
    }

    public function getTypeInfo(): bool|string
    {
        $res['data'] = self::getTypeArray();
        return json_encode($res, 320);
    }

    /**
     * 获取物料分类数据
     *
     * @return array
     */
    public static function getTypeArray($where = ''): array
    {
        $where      = $where ?: " coid = '".self::$coid."' and pid = '0'";
        $where      .= ' order by list asc,time asc';
        $data       = [];
        $material_type = find(['table' => 'material_type', 'field' => 'id, name as deptname', 'where' => $where]);
        foreach ($material_type['array'] as $value) {
            $value['deptname'] = html_entity_decode($value['deptname']);
            $value['type']     = 'department';
            $value['icon']     = root . 'img/control/department.svg';
            // 获取当前部门的职位
            $value['children'] = self::recursiveType('material_type', 'DISTINCT id,name as deptname,list,time', " coid = '".self::$coid."' and pid = '{$value['id']}' order by list asc,time asc ");
            $data[] = $value;
        }
        return $data;
    }


    /**
     * 物料分类选择器
     *
     * @return bool|string
     */
    public function materialTypeTree(): bool|string
    {
        // 赋值的ID
        $id    = $this->post('id') ?? 'field-dept';
        $range = $this->post('range') ?? '';
        $other = $this->post('other') ?? '';
        // 会写的box id
        $boxId = str_replace('layer', '', $id);
        $html  = <<<EOT
        <div class="multi-staff clearfix">
            <div class="multi-staff-left">
                <div class="multi-staff-left-cnt">
                    <!--loading-->
                    <div class="search-loading loading-left-wrap js-search-loading"><span
                            class="search-loadingIconSmall"></span><span
                            class="search-loading-text">正在搜索，请稍候…</span>
                    </div>
                    <!--jstree-->
                    <div id="partyTree" class="multi-staff-left-cnt-list">
                        <div class="search-loading js-search-loading"><span
                                class="search-loadingIconSmall"></span><span
                                class="search-loading-text">正在搜索，请稍候…</span></div>
                        <div class="ztree-wrapper">
                            <ul id="ztreeArea" class="ztree"></ul>
                        </div>
                    </div>
                    <div class="multi-staff-left-mask js-left-mask"></div>
                </div>
            </div>
            <div class="multi-staff-right">
                <div class="multi-staff-right-title">已选择的分类</div>
                <div class="multi-staff-right-cnt">
                    <div class="js-right-col">
                        <ul id="saveNode"></ul>
                    </div>
                    <div class="multi-staff-right-no-result">未选择分类</div>
                </div>
            </div>
        </div>
EOT;
        $button = "<button type='button' class='button' id='confirm-material' data-boxId='$boxId'>确认选择</button>";
        $html  .= <<<EOT
        <script src="{$this->root}static/javascript/ztree.ext.js"></script>
        <script>
        $(function () {
            // 调用
            $('.winAuto').orgTree({
                all: true, //人物组织都开启
                text: '$id', // 赋值的文本框ID
                search: true, //开启搜索
                range: '$range', //范围
                other: '$other', //其他参数
                boxId: '$boxId',
                type:'materialType',
            });
        });
        </script>
EOT;

        //返回
        return $this->layer(array("title" => L('audit.table.xzwlfl'), "height" => 550, 'width' => 650, "html" => $html, "button" => $button, 'zindex' => 13));
    }

}
